
/**
 * @en Utility class for forming the data that is sent to the SideChannel.
 * @zh 用于格式化发送到侧通道的数据的工具类。
 */
export class OutgoingMessage {
    private _buffer: ArrayBuffer = null!;
    private _writer: DataView = null!;
    private _offset: number = 0;

    constructor() {
        this._buffer = new ArrayBuffer(1024);
        this._writer = new DataView(this._buffer);
        this._offset = 0;
    }

    public dispose(): void {

    }

    public writeBoolean(b: boolean): void {
        this.ensureCapacity(1);
        this._writer.setUint8(this._offset, b ? 1 : 0);
        this._offset += 1;
    }

    public writeInt32(i: number): void {
        this.ensureCapacity(4);
        this._writer.setInt32(this._offset, i, true);
        this._offset += 4;
    }

    public writeFloat32(f: number): void {
        this.ensureCapacity(4);
        this._writer.setFloat32(this._offset, f, true);
        this._offset += 4;
    }

    public writeString(s: string): void {
        const encoder = new TextEncoder();
        const encoded = encoder.encode(s);
        this.writeInt32(encoded.length);
        for (const b of encoded) {
            this._writer.setUint8(this._offset, b);
            this._offset += 1;
        }
    }


    public writeFloatList(floatList: number[]): void {
        this.writeInt32(floatList.length);
        for (const f of floatList) {
            this.writeFloat32(f);
        }
    }

    public setRawBytes(data: Uint8Array): void {
        this._offset = 0;
        this._buffer = new ArrayBuffer(data.length);
        for (const b of data) {
            this.ensureCapacity(1);
            this._writer.setUint8(this._offset, b);
            this._offset += 1;
        }
    }

    /**
     * @en Read the byte array of the message.
     * @zh 读取消息的字节数组。
     */
    public toByteArray(): Uint8Array {
        return new Uint8Array(this._buffer, 0, this._offset);
    }

    private ensureCapacity(size: number) {
        if (this._offset + size > this._buffer.byteLength) {
            const newBuffer = new ArrayBuffer(this._buffer.byteLength * 2);
            new Uint8Array(newBuffer).set(new Uint8Array(this._buffer));
            this._buffer = newBuffer;
            this._writer = new DataView(this._buffer);
        }
    }
}